package com.lz.yz.outing.util;

import com.lz.yz.outing.config.InitConfig;
import com.lz.yz.outing.config.MD5;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@Repository
public class Signature {

    private static Logger logger = LoggerFactory.getLogger(Signature.class);
    @Autowired
    private InitConfig initConfig;

    /**
     * 签名算法
     *
     * @param map 要参与签名的数据对象
     * @return 签名
     * @throws IllegalAccessException
     */
    public static String getSign(Map<String,Object> map,String key) {
        StringBuffer sb = new StringBuffer();
        SortedMap<String,Object> sort=new TreeMap<>(map);
        Set es = sort.entrySet();//所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + key);
        String result = MD5.MD5Encode(sb.toString()).toUpperCase();
        return result;
    }

    /**
     * 检验API返回的数据里面的签名是否合法，避免数据在传输的过程中被第三方篡改(公众号)
     *
     * @param responseString API返回的XML数据字符串
     * @return API签名是否合法
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public boolean checkIsSignValidFromResponseString(String responseString,String key) throws ParserConfigurationException, IOException, SAXException,IllegalAccessException {

        Map<String, Object> map = XMLParser.getMapFromXML(responseString);

        String signFromAPIResponse = map.get("sign").toString();
        if (StringUtils.isBlank(signFromAPIResponse) || signFromAPIResponse == null) {
            return false;
        }
//        Util.log("服务器回包里面的签名是:" + signFromAPIResponse);
        //清掉返回数据对象里面的Sign数据（不能把这个数据也加进去进行签名），然后用签名算法进行签名
        map.put("sign","");
        //将API返回的数据根据用签名算法进行计算新的签名，用来跟API返回的签名进行比较
        String signForAPIResponse = this.getSign(map,key);

        if (!signForAPIResponse.equals(signFromAPIResponse)) {
            //签名验不过，表示这个API返回的数据有可能已经被篡改了
//            Util.log("API返回的数据签名验证不通过，有可能被第三方篡改!!!");
            return false;
        }
//        Util.log("恭喜，API返回的数据签名验证通过!!!");
        return true;
    }


    public static String getFqlSign(Map<String, Object> map) {
        ArrayList<String> list = new ArrayList<String>();
        String result = "";
        try {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getValue() != "" && !entry.getValue().equals("")) {
                    list.add(entry.getKey() + "=" + URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8") + "&");
                }
            }
            int size = list.size();
            String[] arrayToSort = list.toArray(new String[size]);
            Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < size; i++) {
                sb.append(arrayToSort[i]);
            }
            result = sb.toString();
//            result += "key=" + FqlConfig.PARTNER_KEY;
//            logger.error("拼装字符串：" + result);
            result = MD5.MD5Encode(result).toLowerCase();
        } catch (Exception e) {
            logger.error("分期乐签名失败", e);
        }

        return result;
    }

    public static String fqlSign(Map<String, Object> map) {
        ArrayList<String> list = new ArrayList<String>();
        String result = "";
        try {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getValue() != "" && !entry.getValue().equals("")) {
                    list.add(entry.getKey() + "=" + entry.getValue() + "&");
                }
            }
            int size = list.size();
            String[] arrayToSort = list.toArray(new String[size]);
            Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < size; i++) {
                sb.append(arrayToSort[i]);
            }
            result = sb.toString();
//            result += "key=" + FqlConfig.PARTNER_KEY;
//            logger.error("拼装字符串(没有进行urlencode)：" + result);
            result = MD5.MD5Encode(result).toLowerCase();
        } catch (Exception e) {
            logger.error("分期乐签名失败", e);
        }

        return result;
    }

}
